/*
   author:qianbo
   418511899@qq.com
   微信:18091589062
*/

const WebSocket = require('ws');
const http = require('http');
const server = http.createServer();
const url = require('url');
//const HashMap = require('hashmap');
//房间的集合
let rooms = new Map();

const ws_server = new WebSocket.Server({ server });
//创建rooms
function noop() { }



server.on('upgrade', function upgrade(request, socket, head) {
  //  const pathname = url.parse(request.url).pathname;
  //  console.log(pathname);
});

function send_string(self, data, ws) {
  // self_include (0 or 1) 0：转发，不需要发送自己，1：群发，包括自己
  let rn = ws._room_name;
  if (rn != null && rooms.has(rn)) {
    let room = rooms.get(rn);
    room.forEach(function (_ws) {
      //给每个人发送
      if (_ws.readyState === WebSocket.OPEN) {
        //不用给自己发送
          //if (self_include == 1) // 需要发送给自己
           //   _ws.send(JSON.stringify(jdata));
        //else // 不需要发送给自己
          if (_ws !== ws) // 发送给房间内其他人
            _ws.send(data);
      }
    });
  }
}


function add_member(ws) {
    let room = rooms.get(ws._room_name);
    let id = ws._name;
    console.log("add_member:",id);
    if (room != null) {
        for (var key of room.keys()) {
            console.log(key);
        }
        if (room.has(id)) { //存在该ID
            let oldws = room.get(id);
            oldws.terminate();
            //room_map.delete(id);
            room.set(id, ws);
            
        }
        else { //not exist this ID
            room.set(id, ws);
        }
    }
}

function send_member(ws) {
  // 获取房间路由（房间号）
    let rn = ws._room_name;
    let name = ws._name;
  if (rn != null && rooms.has(rn)) {
    let room = rooms.get(rn);
    let group = "l2:"; //login cmd
      //room.forEach(function(_ws,name)
    let gnum = 0;
    room.forEach(function (_ws) {
        //给每个人发送
        if (_ws !== ws && _ws.readyState === WebSocket.OPEN) {
            console.log("now is ", gnum);
            gnum++;
            group += _ws._name;
            group += "\n";
            _ws.send("l2:" + name); //login 
           // _ws.send(JSON.stringify(ws.logininfo));
        }
    });
    if(gnum >0)
        ws.send(group);
    //let l = { type: 'login', body: { list: logininfos } };
    //ws.send(JSON.stringify(l));
  }
}
function send_login_out(ws) {
    if (ws._name == null)//not login so do nothing
        return;
    let rn = ws._room_name;
    if (rn != null && rooms.has(rn)) {
        let room = rooms.get(rn);
        let data = "l2:" + ws._name; //login
        console.log("send_login_out:", data);
        if(room != null){
            room.forEach(function (_ws) {
                //not send to self
                if (_ws !== ws && _ws.readyState === WebSocket.OPEN) {
                    _ws.send(data);
                    //_ws.send(JSON.stringify(jdata));
                }
            });
            room.delete(ws._name);
        }
    }
}

ws_server.on('connection', function connection(ws, req, client) {
  ws.isAlive = true;
  // const route_name = url.parse(ws.upgradeReq.url).pathname;
    // 获取房间路由（房间号） pathname 是房间号
  let rn = url.parse(req.url).pathname;
  if(rn.length >1){
      if(rn[0] == '/')
          rn = rn.substring(1);
  } 
  ws._room_name = rn;

   
  //var room = null;
  if (!rooms.has(ws._room_name)) { //存在该房间
      //rooms.get(ws.route_name).add(ws);
      console.log("connection add room---",ws._room_name)
      let room = new Map();
      rooms.set(ws._room_name, room);
  }

  ws.on('pong', function () {
    this.isAlive = true;
    //console.log("pong");
  });
  ws.on('message', function incoming(data) {
      if (data.length < 3) {
          console.log("invalide message");
          return;
      }
      let mess = data.toString();
      console.log("recv %s\n", mess);
      let c1 = mess[0];
      let c2 = mess[1];
      if (c1 != 'c') {
          console.log("invalide first character");
          console.log("first is: %c", c1);
          return;
      }
      let t = mess.substring(3);
      //console.log(t);
      let s = t.split("\n");
      if (s.length < 3) {
          console.log("not ok");
          ws.send("c1:error");
          ws.terminate();
      }
      console.log(s);
      switch(c2)
      {
          case "1":
              console.log("login",s[0]);
              //if (s[0] == "qianbo" && s[1] == "qianbo") {
                  ws._name = s[0];
                  if (ws._room_name != s[2]) {
                      console.log("the roomname compare the url not right");
                      ws.send("e2:room not right");
                      ws.terminate();
                      return;
                  }
                  ws.send("e2:ok"); //system error ok
                  add_member(ws);
                  send_member(ws);
              //}
              //else
                //  ws.send("e2:fa");//system error fail
              break;
          case "2":
              break;
          case "3"://chat
              send_string(0, data, ws);
              break;
          case "4":
              break;
      }


  });
  ws.on('close', function () {
      console.log(ws._name,":close");
      send_login_out(ws);
  });

});


if (0) {
    const interval = setInterval(function ping() {
        ws_server.clients.forEach(function each(ws) {
            if (ws.isAlive === false)
                return ws.terminate();

            ws.isAlive = false;
            ws.ping(noop);
        });
    }, 10000);
}
let port = 8000;
server.listen(port);
console.log("server run at", port);

/*
1 cmd         c1:
如websocket发送登录   c1:abcdef\npassword\nroomid
服务端截取前两个字节 c1,为鉴权 命令   abcdef 为用户名 password 为密码  roomid为房间id号
返回    1 动态口令给用户，用户端可以开启传输流
2 返回媒体服务器ip，port    [多个服务器返回其中一个最快的，负载均衡]
                   3 返回备份媒体服务器ip，port
     
2 content    c2:
如websocket发送   c2:c
2.1  白板内容为一副图片，客户只能看不能操作
图片为减后的图片
内容为流h264，在web端可以做到，客户端更加可以
2.2  客户可以操作       
传输图片，减后的图片，不使用图形，图形过于复杂 ，协议全部更简单          
3 chat         c3:
如websocket发送c3:这是聊天内容
c3::abc:这里是聊天内容  abc是单独某一个人
  
4 connect   c4:  c4:a->b
一对一 链接某个人
*/